Added back __CARGO_DEFAULT_LIB_METADATA handling with comment + test
authorNipunn Koorapati <nipunn1313@gmail.com>
Sun, 13 Nov 2016 02:55:07 +0000 (18:55 -0800)
committerNipunn Koorapati <nipunn1313@gmail.com>
Sun, 13 Nov 2016 02:55:07 +0000 (18:55 -0800)
src/cargo/ops/cargo_rustc/context.rs
tests/build.rs

index 4359cbc14a93c901ef8ee83dc3e4ef9ceb65b044..a1552d63654353ed6300c6cf1964bec1aa851b27 100644 (file)
@@ -308,11 +308,31 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
     }
 
     /// Get the metadata for a target in a specific profile
+    /// We build to the path: "{filename}-{target_metadata}"
+    /// We use a linking step to link/copy to a predictable filename
+    /// like `target/debug/libfoo.{a,so,rlib}` and such.
     pub fn target_metadata(&self, unit: &Unit) -> Option<Metadata> {
         // No metadata for dylibs because of a couple issues
         // - OSX encodes the dylib name in the executable
         // - Windows rustc multiple files of which we can't easily link all of them
-        if !unit.profile.test && unit.target.is_dylib() {
+        //
+        // Two expeptions
+        // 1) Upstream dependencies (we aren't exporting + need to resolve name conflict)
+        // 2) __CARGO_DEFAULT_LIB_METADATA env var
+        //
+        // Note, though, that the compiler's build system at least wants
+        // path dependencies (eg libstd) to have hashes in filenames. To account for
+        // that we have an extra hack here which reads the
+        // `__CARGO_DEFAULT_METADATA` environment variable and creates a
+        // hash in the filename if that's present.
+        //
+        // This environment variable should not be relied on! It's
+        // just here for rustbuild. We need a more principled method
+        // doing this eventually.
+        if !unit.profile.test &&
+            unit.target.is_dylib() &&
+            unit.pkg.package_id().source_id().is_path() &&
+            !env::var("__CARGO_DEFAULT_LIB_METADATA").is_ok() {
             return None;
         }
 
index ac274de22a64788f92fa95ba9f91a72f3e7fcf23..decfa8ed52e3f05d57b401c0ac7f0f42dcfa6106 100644 (file)
@@ -417,6 +417,8 @@ fn cargo_compile_with_nested_deps_inferred() {
         .unwrap();
 
     assert_that(&p.bin("foo"), existing_file());
+    assert_that(&p.bin("libbar.rlib"), is_not(existing_file()));
+    assert_that(&p.bin("libbaz.rlib"), is_not(existing_file()));
 
     assert_that(
       process(&p.bin("foo")),
@@ -476,6 +478,8 @@ fn cargo_compile_with_nested_deps_correct_bin() {
         .unwrap();
 
     assert_that(&p.bin("foo"), existing_file());
+    assert_that(&p.bin("libbar.rlib"), is_not(existing_file()));
+    assert_that(&p.bin("libbaz.rlib"), is_not(existing_file()));
 
     assert_that(
       process(&p.bin("foo")),
@@ -544,6 +548,8 @@ fn cargo_compile_with_nested_deps_shorthand() {
         .unwrap();
 
     assert_that(&p.bin("foo"), existing_file());
+    assert_that(&p.bin("libbar.rlib"), is_not(existing_file()));
+    assert_that(&p.bin("libbaz.rlib"), is_not(existing_file()));
 
     assert_that(
       process(&p.bin("foo")),
@@ -612,6 +618,8 @@ fn cargo_compile_with_nested_deps_longhand() {
     assert_that(p.cargo_process("build"), execs());
 
     assert_that(&p.bin("foo"), existing_file());
+    assert_that(&p.bin("libbar.rlib"), is_not(existing_file()));
+    assert_that(&p.bin("libbaz.rlib"), is_not(existing_file()));
 
     assert_that(process(&p.bin("foo")),
                 execs().with_stdout("test passed\n"));
@@ -754,6 +762,84 @@ fn ignores_carriage_return_in_lockfile() {
                 execs().with_status(0));
 }
 
+#[test]
+fn cargo_default_env_metadata_env_var() {
+    // Ensure that path dep + dylib + env_var get metadata
+    // (even though path_dep + dylib should not)
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [package]
+            name = "foo"
+            version = "0.0.1"
+            authors = []
+
+            [dependencies.bar]
+            path = "bar"
+        "#)
+        .file("src/lib.rs", "// hi")
+        .file("bar/Cargo.toml", r#"
+            [package]
+            name = "bar"
+            version = "0.0.1"
+            authors = []
+
+            [lib]
+            name = "bar"
+            crate_type = ["dylib"]
+        "#)
+        .file("bar/src/lib.rs", "// hello");
+
+    // No metadata on libbar since it's a dylib path dependency
+    assert_that(p.cargo_process("build").arg("-v"),
+                execs().with_status(0).with_stderr(&format!("\
+[COMPILING] bar v0.0.1 ({url}[/]bar)
+[RUNNING] `rustc bar[/]src[/]lib.rs --crate-name bar --crate-type dylib \
+        -C prefer-dynamic -g \
+        -C metadata=[..] \
+        --out-dir [..] \
+        --emit=dep-info,link \
+        -L dependency={dir}[/]target[/]debug[/]deps`
+[COMPILING] foo v0.0.1 ({url})
+[RUNNING] `rustc src[/]lib.rs --crate-name foo --crate-type lib -g \
+        -C metadata=[..] \
+        -C extra-filename=[..] \
+        --out-dir [..] \
+        --emit=dep-info,link \
+        -L dependency={dir}[/]target[/]debug[/]deps \
+        --extern bar={dir}[/]target[/]debug[/]deps[/]libbar.dylib`
+[FINISHED] debug [unoptimized + debuginfo] target(s) in [..]
+",
+dir = p.root().display(),
+url = p.url(),
+)));
+
+    assert_that(p.cargo_process("clean"), execs().with_status(0));
+
+    // If you set the env-var, then we expect metadata on libbar
+    assert_that(p.cargo_process("build").arg("-v").env("__CARGO_DEFAULT_LIB_METADATA", "1"),
+                execs().with_status(0).with_stderr(&format!("\
+[COMPILING] bar v0.0.1 ({url}[/]bar)
+[RUNNING] `rustc bar[/]src[/]lib.rs --crate-name bar --crate-type dylib \
+        -C prefer-dynamic -g \
+        -C metadata=[..] \
+        --out-dir [..] \
+        --emit=dep-info,link \
+        -L dependency={dir}[/]target[/]debug[/]deps`
+[COMPILING] foo v0.0.1 ({url})
+[RUNNING] `rustc src[/]lib.rs --crate-name foo --crate-type lib -g \
+        -C metadata=[..] \
+        -C extra-filename=[..] \
+        --out-dir [..] \
+        --emit=dep-info,link \
+        -L dependency={dir}[/]target[/]debug[/]deps \
+        --extern bar={dir}[/]target[/]debug[/]deps[/]libbar-[..].dylib`
+[FINISHED] debug [unoptimized + debuginfo] target(s) in [..]
+",
+dir = p.root().display(),
+url = p.url(),
+)));
+}
+
 #[test]
 fn crate_env_vars() {
     let p = project("foo")